﻿using NPOI.SS.Formula.Functions;
using NPOI.XWPF.UserModel;
using System.Data;
using System.Reflection;
using System.Text;
using System.Text.Json.Serialization;
using TableTools.Models;

namespace TableTools.Handlers
{
    public class DocxTableHandler : ITableHandler
    {
        //private Dictionary<string, List<ClassInfo>> GetClassInfo(Type type)
        //{
        //    Dictionary<string, List<ClassInfo>> classMap = new Dictionary<string, List<ClassInfo>>();
        //    if (classMap.ContainsKey(type.Name))
        //    {
        //        return classMap;
        //    }
        //    List<ClassInfo> props = new List<ClassInfo>();
        //    foreach (var field in type.GetProperties())
        //    {

        //        var fieldType = field.PropertyType;
        //        if (fieldType.IsPrimitive || fieldType.Name.ToLower().Equals("string"))
        //        {
        //            var name = field.GetCustomAttribute<JsonPropertyNameAttribute>().Name;
        //            props.Add(new ClassInfo(name, field.Name, ToType(fieldType.Name), string.Empty));
        //        }
        //        else if (fieldType.IsGenericType)
        //        {
        //            var name = field.GetCustomAttribute<JsonPropertyNameAttribute>().Name;
        //            var listItemType = fieldType.GetGenericArguments()[0];
        //            if (!listItemType.IsPrimitive && !listItemType.Name.ToLower().Equals("string"))
        //            {
        //                props.Add(new ClassInfo(name, field.Name, $"List<{listItemType.Name}>", string.Empty));
        //                foreach (var item in GetClassInfo(listItemType))
        //                {
        //                    if (classMap.ContainsKey(item.Key))
        //                    {
        //                        continue;
        //                    }
        //                    classMap.Add(item.Key, item.Value);
        //                }
        //            }
        //            else
        //            {
        //                props.Add(new ClassInfo(name, field.Name, $"List<{ToType(listItemType.Name)}>", string.Empty));
        //            }
        //        }
        //        else if (fieldType.IsClass)
        //        {
        //            var name = field.GetCustomAttribute<JsonPropertyNameAttribute>().Name;
        //            props.Add(new ClassInfo(name, field.Name, fieldType.Name, string.Empty));
        //            foreach (var item in GetClassInfo(fieldType.GetType()))
        //            {
        //                if (classMap.ContainsKey(item.Key))
        //                {
        //                    continue;
        //                }
        //                classMap.Add(item.Key, item.Value);
        //            }
        //        }
        //    }
        //    classMap.Add(type.Name, props);
        //    return classMap;
        //}

        //private string ToType(string type)
        //    => type switch
        //    {
        //        "String" => "string",
        //        "Int32" => "int",
        //        "Int64" => "long",
        //        "Decimal" => "decimal",
        //        "Boolean" => "bool",
        //        "Object" => "object",
        //    };

        public TableResult ToTable(string path)
        {
            TableResult result = new TableResult();

            using var doc = new XWPFDocument(File.OpenRead(path));
            foreach (var table in doc.Tables)
            {
                var template = new TableTemplate();
                var rows = new List<string[]>();
                for (int i = 0; i < table.Rows.Count; i++)
                {
                    var row = table.Rows[i];
                    var cells = row.GetTableCells();
                    var cellsArr = cells.Select(x => x.GetText()).ToArray();
                    if (cellsArr.Any(x => !string.IsNullOrWhiteSpace(x)))
                    {
                        rows.Add(cellsArr);
                    }
                }
                if(rows.Count == 0)
                {
                    continue;
                }
                var maxCol = rows.Max(x => x.Length);
                template.Table = new TableInfo(rows.Count - 1, maxCol);
                for (int j = 0; j < rows[0].Length; j++)
                {
                    template.Table.Headers[j] = rows[0][j];
                }
                for (int i = 0; i < rows.Count - 1; i++)
                {
                    var clos = rows[i + 1];
                    for (int j = 0; j < clos.Length; j++)
                    {
                        template.Table.Rows[i][j] = clos[j];
                    }
                }
                result.Add(template);
            }

            try
            {
                // 合并表格，word可能存在跨页表格拆分
                var headName = result.Tables.GroupBy(x => x.Table.Headers[0]).MaxBy(x => x.Count()).Key;

                var tables = result.Tables.AsEnumerable().ToList();

                for (int i = 1; i < tables.Count; i++)
                {
                    var table = tables[i];
                    if (headName != table.Table.Headers[0])
                    {
                        var afterTable = tables[i - 1];
                        var row = afterTable.Table.Rows.Length + 1 + table.Table.Rows.Length;
                        var col = afterTable.Table.Headers.Length;
                        var rows = new string[row][];
                        for (int j = 0; j < row; j++)
                        {
                            rows[j] = new string[col];
                        }
                        for (int j = 0; j < afterTable.Table.Rows.Length; j++)
                        {
                            var afterRows = afterTable.Table.Rows[j];
                            for (int k = 0; k < afterRows.Length; k++)
                            {
                                rows[j][k] = afterRows[k];
                            }
                        }
                        var minCol = Math.Min(table.Table.Headers.Length, afterTable.Table.Headers.Length);
                        for (int j = 0; j < minCol; j++)
                        {
                            rows[afterTable.Table.Rows.Length][j] = table.Table.Headers[j];
                        }
                        for (int j = afterTable.Table.Rows.Length + 1; j < row; j++)
                        {
                            var curRows = table.Table.Rows[j - afterTable.Table.Rows.Length - 1];
                            for (int k = 0; k < minCol; k++)
                            {
                                rows[j][k] = curRows[k];
                            }
                        }
                        afterTable.Table.Row = row;
                        afterTable.Table.Col = col;
                        afterTable.Table.Rows = rows;
                        result.Tables.Remove(table);
                    }
                }

                for (int i = 0; i < result.Tables.Count; i++)
                {
                    var table = result.Tables[i];
                    table.Index = i;
                }
            }
            catch (Exception e)
            {
                
            }

            return result;
        }
    }
}
